package cn.fuxi2022.module.pay.service.impl;

import cn.fuxi2022.core.exception.SmartGroupException;
import cn.fuxi2022.core.utils.ExecutortUtils;
import cn.fuxi2022.model.empty.count.BarChart;
import cn.fuxi2022.model.empty.count.BasicBar;
import cn.fuxi2022.model.empty.count.DoughnutChart;
import cn.fuxi2022.model.empty.count.TempChart;
import cn.fuxi2022.module.pay.mapper.GroupStudentPayLogMapper;
import cn.fuxi2022.module.pay.service.GroupStudentPayLogCountService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ThreadPoolExecutor;

@Slf4j
@Service
public class GroupStudentPayLogCountServiceImpl implements GroupStudentPayLogCountService {

    @Autowired
    private GroupStudentPayLogMapper groupStudentPayLogMapper;

    @Override
    @Cacheable(value = "SmartGroup:pay", key = "'groupStudentPayLogCount'")
    public Map groupStudentPayLogCount() {

        long l1 = System.currentTimeMillis();

        // 创建线程池
        ThreadPoolExecutor threadPool = ExecutortUtils.getThreadPool();
        threadPool.submit(() -> {
        });

        // 线程1
        CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> groupStudentPayLogMapper.countPayLog(), ExecutortUtils.getThreadPool());

        // 线程2
        CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(() -> groupStudentPayLogMapper.payUseTime(), ExecutortUtils.getThreadPool());

        // 线程3
        CompletableFuture<Integer> future3 = CompletableFuture.supplyAsync(() -> groupStudentPayLogMapper.sumPayTotal(), ExecutortUtils.getThreadPool());

        // 线程4
        CompletableFuture<List<DoughnutChart>> future4 = CompletableFuture.supplyAsync(this::isAndNotPayStudentCount, ExecutortUtils.getThreadPool());

        // 线程5
        CompletableFuture<BarChart> future5 = CompletableFuture.supplyAsync(this::orderMostStudent, ExecutortUtils.getThreadPool());

        // 线程6
        CompletableFuture<BarChart> future6 = CompletableFuture.supplyAsync(this::orderFastStudent, ExecutortUtils.getThreadPool());

        // 线程7
        CompletableFuture<BasicBar> future7 = CompletableFuture.supplyAsync(this::orderMostTime, ExecutortUtils.getThreadPool());

        // 线程8
        CompletableFuture<List<DoughnutChart>> future8 = CompletableFuture.supplyAsync(this::orderStatusToMap, ExecutortUtils.getThreadPool());

        CompletableFuture<List<DoughnutChart>> future9 = CompletableFuture.supplyAsync(() -> groupStudentPayLogMapper.orderTime());

        try {
            CompletableFuture.allOf(future1, future2, future3, future4, future5, future6, future7, future8,future9).get();
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
            throw new SmartGroupException("多线程统计数据失败");
        }

        long l2 = System.currentTimeMillis();

        log.info("groupStudentPayLogCount统计耗时时间{}", l2 - l1);

        HashMap<String, Object> data = new HashMap<>();
        try {
            data.put("countPayLog", future1.get());
            data.put("payUseTime", future2.get());
            data.put("sumPayTotal", future3.get());
            data.put("isAndNotPayStudentCount", future4.get());
            data.put("orderMostStudent", future5.get());
            data.put("orderFastStudent", future6.get());
            data.put("orderMostTime", future7.get());
            data.put("orderStatus", future8.get());
            data.put("orderTime", future9.get());
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
            throw new SmartGroupException("多线程统计获取数据失败");
        }

        return data;
    }

    @CacheEvict(value = "SmartGroup:pay", key = "'groupStudentPayLogCount'")
    @Override
    public void groupStudentPayLogRefresh() {
        log.info("groupStudentPayLogCount缓存已经清空");
    }

    public List<DoughnutChart> isAndNotPayStudentCount() {
        ArrayList<DoughnutChart> list = new ArrayList<>();

        list.add(groupStudentPayLogMapper.isPayStudentCount());
        list.add(groupStudentPayLogMapper.noPayStudentCount());

        return list;
    }

    public BarChart orderMostStudent() {
        return setBarChart(groupStudentPayLogMapper.orderMostStudent());
    }

    public BarChart orderFastStudent() {
        return setBarChart(groupStudentPayLogMapper.orderFastStudent());
    }

    public BasicBar orderMostTime() {
        return setBasicBar(groupStudentPayLogMapper.orderMostTime());
    }

    public List<DoughnutChart> orderStatusToMap() {
        List<DoughnutChart> doughnutCharts = groupStudentPayLogMapper.orderStatusToMap();
        doughnutCharts.forEach(doughnutChart -> {
            switch (doughnutChart.getName()) {
                case "0":
                    doughnutChart.setName("未支付");
                    break;
                case "1":
                    doughnutChart.setName("已支付");
                    break;
                case "2":
                    doughnutChart.setName("支付关闭");
                    break;
                case "3":
                    doughnutChart.setName("支付超时");
                    break;
                case "4":
                    doughnutChart.setName("已退款");
                    break;
                default:
                    doughnutChart.setName("未知");
            }
        });

        return doughnutCharts;
    }

    public BarChart setBarChart(List<TempChart> tempCharts) {
        ArrayList<String> yAxis = new ArrayList<>();
        ArrayList<Integer> data = new ArrayList<>();

        tempCharts.forEach(tempChart -> {
            yAxis.add(tempChart.getName());
            data.add(tempChart.getValue());
        });

        BarChart barChart = new BarChart();
        barChart.setYAxis(yAxis);
        barChart.setData(data);
        return barChart;
    }

    public BasicBar setBasicBar(List<TempChart> tempCharts) {
        ArrayList<String> xAxis = new ArrayList<>();
        ArrayList<Integer> data = new ArrayList<>();

        tempCharts.forEach(tempChart -> {
            xAxis.add(tempChart.getName());
            data.add(tempChart.getValue());
        });

        BasicBar barChart = new BasicBar();
        barChart.setXAxis(xAxis);
        barChart.setData(data);
        return barChart;
    }

}
